package org.bimon.handler;

import org.bimon.constant.KNNInfo;
import org.bimon.manager.EnvironmentManager;
import org.bimon.manager.FileManager;
import org.bimon.model.KNNDataset;

import java.util.*;

public abstract class AbstractHandler {

    protected FileManager fileManager = new FileManager();

    protected EnvironmentManager environmentManager = new EnvironmentManager();

    /**
     * 行列互换
     *
     * @param dataset
     * @return
     */
    protected List<List<Double>> rowColumnInterchange(List<List<Double>> dataset) {
        if (null == dataset || dataset.size() == 0) {
            return dataset;
        }

        List<List<Double>> toList = new ArrayList<List<Double>>();
        Map<Integer, List<Double>> map = new HashMap<Integer, List<Double>>();

        for (int i = 0; i < dataset.size(); i++) {
            List<Double> row = dataset.get(i);

            for (int j = 0; j < row.size(); j++) {
                Double cell = row.get(j);

                List<Double> col = map.get(j);
                if (col == null) {
                    col = new ArrayList<Double>();
                }
                col.add(cell);
                map.put(j, col);
            }
        }

        List<Integer> sort = new ArrayList<Integer>(map.keySet());
        Collections.sort(sort);

        for (Integer key : sort) {
            toList.add(map.get(key));
        }

        return toList;
    }

    /**
     * 归一化
     *
     * @param dataset
     * @return
     */
    protected List<List<Double>> normalize(List<List<Double>> dataset) {
        List<List<Double>> newDataset = new ArrayList<>();
        for (int i = 0; i < dataset.size(); ++i) {
            List<Double> columnList = dataset.get(i);
            double max = columnList.get(0);
            double min = columnList.get(0);
            for (int j = 0; j < columnList.size(); j++) {
                Double column = columnList.get(j);
                if (column.compareTo(max) > 0) {
                    max = column;
                }
                if (column.compareTo(min) < 0) {
                    min = column;
                }
            }
            List<Double> newColumnList = new ArrayList<>();
            for (int k = 0; k < columnList.size(); ++k) {
                newColumnList.add((columnList.get(k).doubleValue() - min) / (max - min));
            }
            newDataset.add(newColumnList);
        }
        return newDataset;
    }

    /**
     * 区分训练数据集、训练数据集标签、测试数据集、测试数据集标签
     * @param rowColumnInterchangeList
     * @return
     */
    protected KNNDataset differentiateTrainingDatasetAndTestingDataset(List<List<Double>> rowColumnInterchangeList, List<String> labelList){
        KNNDataset knnDataset = new KNNDataset();

        int trainingDatasetRowNumber = (int) Math.round(rowColumnInterchangeList.size() * KNNInfo.KNN_TRAINING_DATASET_PERCENTAGE);
        int testingDatasetRowNumber = rowColumnInterchangeList.size() - trainingDatasetRowNumber;
        List<List<Double>> trainingDatasetList = new ArrayList<>();
        List<List<Double>> testingDatasetList = new ArrayList<>();
        List<String> trainingLabelList = new ArrayList<>();
        List<String> testingLabelList = new ArrayList<>();

        if (null != rowColumnInterchangeList && rowColumnInterchangeList.size() > 0){
            for (int i=0; i<rowColumnInterchangeList.size(); i++){
                if (i < trainingDatasetRowNumber){
                    trainingDatasetList.add(rowColumnInterchangeList.get(i));
                    trainingLabelList.add(labelList.get(i));
                } else {
                    testingDatasetList.add(rowColumnInterchangeList.get(i));
                    testingLabelList.add(labelList.get(i));
                }
            }
        }
        knnDataset.setTrainingDataset(trainingDatasetList);
        knnDataset.setTrainingDatasetLabel(trainingLabelList);
        knnDataset.setTestingDataset(testingDatasetList);
        knnDataset.setTestingDatasetLabel(testingLabelList);

        return knnDataset;
    }
}
